package math

import (
	"gvm/instructions/base"
	"gvm/rtda"
	"math"
	"reflect"
	"strings"
)

// 求余
type REM[T interface{}] struct {
	base.NoOperandsInstruction
}

func (self *REM[T]) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	e := reflect.TypeOf(self).Elem().String()
	etype := strings.ReplaceAll(strings.Split(e, "[")[1], "]", "")
	switch etype {
	case "int64":
		v2 := stack.PopLong()
		v1 := stack.PopLong()
		if v2 == 0 {
			panic("java.lang.ArithmeticException: / by zero")
		}
		stack.PushLong(v1 % v2)
		break
	case "int32":
		v2 := stack.PopInt()
		v1 := stack.PopInt()
		if v2 == 0 {
			panic("java.lang.ArithmeticException: / by zero")
		}
		stack.PushInt(v1 % v2)
		break
	case "float32":
		v2 := stack.PopFloat()
		v1 := stack.PopFloat()
		if v2 == 0 {
			panic("java.lang.ArithmeticException: / by zero")
		}
		stack.PushFloat(float32(math.Mod(float64(v1), float64(v2))))
		break
	case "float64":
		v2 := stack.PopDouble()
		v1 := stack.PopDouble()
		if v2 == 0 {
			panic("java.lang.ArithmeticException: / by zero")
		}
		stack.PushDouble(math.Mod(v1, v2))
		break
	}
}

type IREM struct {
	REM[int32]
}

type LREM struct {
	REM[int64]
}

type DREM struct {
	REM[float64]
}

type FREM struct {
	REM[float32]
}
